package com.yami.shop.rights.common.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.enums.DeliveryType;
import com.yami.shop.bean.model.Delivery;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.util.PoiExcelUtil;
import com.yami.shop.common.util.PrincipalUtil;
import com.yami.shop.rights.common.dao.ExchangeRecordMapper;
import com.yami.shop.rights.common.dto.ExchangeRightsDto;
import com.yami.shop.rights.common.model.ExchangeRecord;
import com.yami.shop.rights.common.model.PersonRights;
import com.yami.shop.rights.common.model.RightsRecord;
import com.yami.shop.rights.common.service.ExchangeRecordService;
import com.yami.shop.rights.common.service.PersonRightsService;
import com.yami.shop.rights.common.service.RightsRecordService;
import com.yami.shop.service.DeliveryService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ExchangeRecordServiceImpl extends ServiceImpl<ExchangeRecordMapper, ExchangeRecord> implements ExchangeRecordService {

    @Autowired
    private ExchangeRecordMapper exchangeRecordMapper;
    @Autowired
    private DeliveryService deliveryService;
    @Autowired
    private RightsRecordService rightsRecordService;
    @Autowired
    private PersonRightsService personRightsService;

    @Override
    public IPage<ExchangeRightsDto> pageList(PageParam<ExchangeRightsDto> page, ExchangeRightsDto vo) {
        return exchangeRecordMapper.pageList(page, vo);
    }

    @Override
    public void unDeliveryExchangeExcel(ExchangeRightsDto exchangeRightsDto, HttpServletResponse response) {
        List<ExchangeRightsDto> orderExcelList = exchangeRecordMapper.listUnDeliveryExchangeExcel(exchangeRightsDto);
        //创建writer
        ExcelWriter writer = ExcelUtil.getBigWriter();
        List<String> orderHeaderList;
        String[] orderHeaderCn = {"订单号", "配送方式*", "快递公司名称*（配送方式为快递配送时必填）",
                "快递单号*（配送方式为快递配送时必填）","发货省份*","发货城市*", "收货人姓名", "收货人手机号", "收货地址",
                "商品名称"};
        String[] orderHeaderEn = {"Order Number", "Delivery method", "Express company name(required when the delivery method is express delivery)",
                "Express delivery number", "province", "city", "Consignee's name","Consignee's phone", "Receiving Address"
                , "Product name"};
        orderHeaderList = Arrays.asList(Objects.equals(I18nMessage.getDbLang(), 0) ? orderHeaderCn : orderHeaderEn);
        Sheet sheet = writer.getSheet();
        setSheetColumnWidth(sheet);
        writer.merge(orderHeaderList.size() - 1, "待发货订单信息整理");
        writer.writeRow(orderHeaderList);
        //配送方式
        String[] dvyTypes = {"快递配送", "无需快递", "同城配送"};
        PoiExcelUtil.createDropDownList(sheet, dvyTypes, 2, 50000, 1, 1);
        //快递公司
        List<Delivery> deliveryList = deliveryService.list(new LambdaQueryWrapper<>());
        if (CollUtil.isNotEmpty(deliveryList)) {
            String[] dvyName = new String[deliveryList.size()];
            for (int i = 0; i < deliveryList.size(); i++) {
                dvyName[i] = deliveryList.get(i).getDvyName();
            }
            PoiExcelUtil.createDropDownList(writer.getWorkbook(), sheet, Arrays.asList(dvyName), 2, 50000, 2, 2);
        }
        //写入数据
        int row = 1;
        for (ExchangeRightsDto orderExcel : orderExcelList) {
            row++;
            int col = -1;
            //订单号
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getOrderNumber());
            //配送方式
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, DeliveryType.getDescription(orderExcel.getDvyType()));
            //快递公司名称
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getDvyName());
            //快递单号
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getDvyFlowId());
            //发货省份
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getProvince());
            //发货城市
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getCity());
            //收货人姓名
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getRealmName());
            //收货人手机号
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getPhone());
            //收货地址
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getAddress());
            PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, orderExcel.getProdName());
        }
        PoiExcelUtil.writeExcel(response, writer);
    }

    @Override
    public ExchangeRightsDto getExchangeRecordByOrderNumber(String orderNumber, Long shopId) {
        return exchangeRecordMapper.getExchangeRecordByOrderNumber(orderNumber ,shopId);
    }

    @Override
    public String exportExchangeExcel(MultipartFile orderExcelFile, Long shopId, List<ExchangeRightsDto> exchangeList) {
        try (InputStream inputStream = orderExcelFile.getInputStream();
             Workbook workbook = WorkbookFactory.create(inputStream)) {
            //读取工作表
            Sheet sheet = workbook.getSheetAt(0);
            int allRow = sheet.getPhysicalNumberOfRows();
            //无内容
            if (allRow <= 2) {
                throw new YamiShopBindException("yami.document.no.content");
            }
            // * 2.1不是Excel文件，直接返回提示信息
            if (!(orderExcelFile.getOriginalFilename().contains(Constant.XLS_FILE) || orderExcelFile.getOriginalFilename().contains(Constant.XLSX_FILE))) {
                // 格式错误
                throw new YamiShopBindException("yami.file.error");
            }
            //进行数据校验
            List<Delivery> deliveryList = deliveryService.list(new LambdaQueryWrapper<>());
            Map<String, Long> deliveryCompanyMap = deliveryList.stream().collect(Collectors.toMap(Delivery::getDvyName, Delivery::getDvyId));
            int dvyType = 0;
            int step = 1;
            for (int i = 2; i < allRow; i += step) {
                ExchangeRightsDto unDeliveryOrderExcelVO = new ExchangeRightsDto();
                int trueStep = 1;
                try {
                    trueStep = checkExcel(sheet, i, dvyType, unDeliveryOrderExcelVO, shopId, deliveryCompanyMap, trueStep);
                    step = trueStep;
                } catch (Exception e) {
                    //错误信息提示
                    return "第" + (i + 1) + "行数据有错误," + e.getMessage();
                }
                exchangeList.add(unDeliveryOrderExcelVO);
            }
            return null;
        } catch (Exception e) {
            return e.getMessage();
        }

    }

    @Override
    public void updateStatusByPersonRightsId(String orderNumber) {
        LambdaUpdateWrapper<ExchangeRecord> exchangeRecordLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        exchangeRecordLambdaUpdateWrapper.eq(ExchangeRecord::getOrderNumber,orderNumber);
        ExchangeRecord one1 = exchangeRecordMapper.selectOne(exchangeRecordLambdaUpdateWrapper);
        if(!"3".equals(one1.getStatus())){
            throw new YamiShopBindException("物流状态异常");
        }
        Long personRightsId = one1.getPersonRightsId();
        LambdaUpdateWrapper<RightsRecord> rightsRecordLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        rightsRecordLambdaUpdateWrapper.eq(RightsRecord::getPersonRightsId,personRightsId);
        RightsRecord one = rightsRecordService.getOne(rightsRecordLambdaUpdateWrapper);
        if(!"1".equals(one.getStatus())){
            throw new YamiShopBindException("权益状态异常");
        }
        PersonRights personRights = personRightsService.getById(personRightsId);
        if(personRights.getStatus()!=4){
            throw new YamiShopBindException("权益状态异常");
        }
        LambdaUpdateWrapper<RightsRecord> recordLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        recordLambdaUpdateWrapper.eq(RightsRecord::getId,one.getId());
        recordLambdaUpdateWrapper.set(RightsRecord::getStatus,"2");//如果有地址表示冻结待确认收货后再改为使用
        rightsRecordService.update(recordLambdaUpdateWrapper);

        LambdaUpdateWrapper<PersonRights> personRightsLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        personRightsLambdaUpdateWrapper.eq(PersonRights::getId,personRightsId);
        personRightsLambdaUpdateWrapper.set(PersonRights::getStatus,1);//如果有地址表示冻结待确认收货后再改为使用
        personRightsService.update(personRightsLambdaUpdateWrapper);

        LambdaUpdateWrapper<ExchangeRecord> exchangeRecord1LambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        exchangeRecord1LambdaUpdateWrapper.eq(ExchangeRecord::getId,one1.getId());
        exchangeRecord1LambdaUpdateWrapper.set(ExchangeRecord::getStatus,"5");//物流状态
        exchangeRecordMapper.update(null,exchangeRecord1LambdaUpdateWrapper);
    }

    private void setSheetColumnWidth(Sheet sheet) {
        sheet.setColumnWidth(0, 20 * 256);
        sheet.setColumnWidth(1, 20 * 256);
        sheet.setColumnWidth(2, 40 * 256);
        sheet.setColumnWidth(3, 20 * 256);
        sheet.setColumnWidth(4, 20 * 256);
        sheet.setColumnWidth(5, 30 * 256);
        sheet.setColumnWidth(6, 80 * 256);
        sheet.setColumnWidth(7, 30 * 256);
    }


    private int checkExcel(Sheet sheet, int i, int dvyType, ExchangeRightsDto unDeliveryOrderExcelVO, Long shopId, Map<String, Long> deliveryCompanyMap, int trueStep) {
        Row row = sheet.getRow(i);
        int cellRow = 0;
        String orderNumber = PoiExcelUtil.getRowValue(row, cellRow, false);
        if (Objects.isNull(orderNumber) || orderNumber.length() == 0) {
            //订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        ExchangeRightsDto exchangeRightsDto = exchangeRecordMapper.getExchangeRecordByOrderNumber(orderNumber,shopId);

        if (Objects.isNull(exchangeRightsDto)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }

        String deliveryType = PoiExcelUtil.getRowValue(row, ++cellRow, false);
        if (Objects.isNull(deliveryType) || deliveryType.length() == 0) {
            //请选择配送方式
            throw new YamiShopBindException("yami.product.dvy.type");
        } else if (Objects.equals(deliveryType, DeliveryType.NO_EXPRESS.getDesc())) {
            dvyType = DeliveryType.NO_EXPRESS.getValue();
        } else if (Objects.equals(deliveryType, DeliveryType.SAME_CITY.getDesc())) {
            dvyType = DeliveryType.SAME_CITY.getValue();
        } else if (Objects.equals(deliveryType, DeliveryType.EXPRESS.getDesc())) {
            dvyType = DeliveryType.EXPRESS.getValue();
        }
        if (Objects.equals(dvyType, DeliveryType.SAME_CITY.getValue()) && !Objects.equals(exchangeRightsDto.getDvyType(), DeliveryType.SAME_CITY.getValue())) {
            //当前订单不支持同城配送
            throw new YamiShopBindException("yami.order.same.city.error3");
        }
        //导入的配送方式与订单的配送方式不一致
        //订单的配送方式为快递配送时，导入的配送方式可选择快递配送和无需快递，其他情况订单的配送方式与导入的配送方式需保持一致
//        if(!Objects.equals(exchangeRightsDto.getDvyType(), dvyType) && !Objects.equals(exchangeRightsDto.getDvyType(), DeliveryType.EXPRESS.getValue())){
//            throw new YamiShopBindException("yami.order.devType.notMatch");
//        }else if(!Objects.equals(exchangeRightsDto.getDvyType(), dvyType) && Objects.equals(exchangeRightsDto.getDvyType(), DeliveryType.EXPRESS.getValue())){
//            if(!Objects.equals(dvyType, DeliveryType.NO_EXPRESS.getValue())){
//                throw new YamiShopBindException("yami.order.devType.notMatch");
//            }
//        }
        String dvyName = PoiExcelUtil.getRowValue(row, ++cellRow, false);
        String dvyFlowId = PoiExcelUtil.getRowValue(row, ++cellRow, false);
        if (Objects.equals(deliveryType, DeliveryType.EXPRESS.getDesc())) {
            //只有快递需要校验快递信息
            if (Objects.isNull(dvyName) || dvyName.length() == 0) {
                //快递公司名称不能为空
                throw new YamiShopBindException("yami.order.no.dvyName");
            }
            dvyFlowId = StringUtils.deleteWhitespace(dvyFlowId);
            if (StrUtil.isBlank(dvyFlowId) || dvyFlowId.length() < 4 || dvyFlowId.length() > 30
                    || !PrincipalUtil.isMatching(PrincipalUtil.WITHOUT_CHINESE, dvyFlowId)) {
                //快递单号格式错误
                throw new YamiShopBindException("yami.order.delivery.number");
            }
            unDeliveryOrderExcelVO.setDvyFlowId(dvyFlowId);
            unDeliveryOrderExcelVO.setDvyName(dvyName);
            unDeliveryOrderExcelVO.setDvyId(deliveryCompanyMap.get(dvyName));
        }
        unDeliveryOrderExcelVO.setOrderNumber(orderNumber);
        unDeliveryOrderExcelVO.setDvyType(dvyType);

        String province = PoiExcelUtil.getRowValue(row, ++cellRow, false);
        unDeliveryOrderExcelVO.setProvince(province);
        String city = PoiExcelUtil.getRowValue(row, ++cellRow, false);
        unDeliveryOrderExcelVO.setCity(city);

        unDeliveryOrderExcelVO.setAddress(exchangeRightsDto.getAddress());
        unDeliveryOrderExcelVO.setCreateTime(exchangeRightsDto.getCreateTime());
        unDeliveryOrderExcelVO.setId(exchangeRightsDto.getId());
        unDeliveryOrderExcelVO.setPhone(exchangeRightsDto.getPhone());
        unDeliveryOrderExcelVO.setProdName(exchangeRightsDto.getProdName());
        unDeliveryOrderExcelVO.setRealmName(exchangeRightsDto.getRealmName());
        unDeliveryOrderExcelVO.setShopId(exchangeRightsDto.getShopId());
        unDeliveryOrderExcelVO.setUserId(exchangeRightsDto.getUserId());
        unDeliveryOrderExcelVO.setStatus(exchangeRightsDto.getStatus());
        return trueStep;
    }

}
